package service.role;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.stereotype.Service;

import base.entity.Page;
import base.service.IBaseService;
import entity.role.MyResource;
import entity.role.Role;
import entity.role.RoleResource;
import entity.role.UserRole;
import entity.user.User;
import util.MyConfig;

@Service("roleServiceImpl")
public class RoleServiceImpl implements IRoleService {
	@Resource
	private IBaseService baseServiceImpl;
	@Resource
	private MyConfig myConfig;
	@Override
	public Role addRole(Role role) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.save(role);
		return role;
	}

	@Override
	public Role updateRole(Role role) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.save(role);
		return role;
	}

	@Override
	public void deleteRole(String id) throws Exception {
		// TODO Auto-generated method stub
		Role role = getRoleById(id);
		if (role.getCode() != -1) {
			baseServiceImpl.delete(role);
		}
	}

	@Override
	public Page<Role> getRolesByPageAndSize(Integer pageNo, Integer pageSize) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(Role.class);
		Page<Role> page = baseServiceImpl.findByCriteria(criteria, pageNo, pageSize);
		return page;
	}

	@Override
	public Role getRoleById(String id) throws Exception {
		// TODO Auto-generated method stub
		return baseServiceImpl.getById(Role.class, id);
	}

	@Override
	public Page<UserRole> getUsersByRoleId(Integer pageNo, Integer pageSize, String id) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(UserRole.class);
		criteria.createAlias("role", "r");
		criteria.add(Restrictions.eq("r.id", id));
		Page<UserRole> page = baseServiceImpl.findByCriteria(criteria, pageNo, pageSize);
		return page;
	}

	@Override
	public List<User> getAllUsersFromUserRole(Role role) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(UserRole.class);
		criteria.add(Restrictions.eq("role", role));
		List<UserRole> userRoles = baseServiceImpl.findByCriteria(criteria);
		List<User> users = new ArrayList<>();
		for (UserRole userRole : userRoles) {
			users.add(userRole.getUser());
		}
		return users;
	}

	@Override
	public List<UserRole> addUserToRole(List<UserRole> userRoles) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.save(userRoles);
		return userRoles;
	}

	@Override
	public void deleteUserRoleByIds(List<String> ids) throws Exception {
		// TODO Auto-generated method stub
		List<UserRole> userRoles = baseServiceImpl.getByIdList(UserRole.class, ids);
		baseServiceImpl.delete(userRoles);
	}

	@Override
	public MyResource addResource(MyResource resource) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.save(resource);
		// 给系统超级管理员增加该资源权限
		List<Role> roles = baseServiceImpl.find("from Role where code = ?",
				new Object[] { myConfig.getSuperManagerRoleCode() });
		List<RoleResource> roleResources = new ArrayList<RoleResource>();
		for (Role role : roles) {
			RoleResource roleResource = new RoleResource(role, resource);
			roleResources.add(roleResource);
		}
		baseServiceImpl.save(roleResources);
		return resource;
	}

	@Override
	public Page<MyResource> getResourcesByPageAndSize(Integer pageNo, Integer pageSize) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(MyResource.class);
		criteria.add(Restrictions.isNull("parent"));
		criteria.addOrder(Order.asc("ordernum"));
		Page<MyResource> page = baseServiceImpl.findByCriteria(criteria, pageNo, pageSize);
		return page;
	}

	@Override
	public MyResource getResourceById(String id) throws Exception {
		// TODO Auto-generated method stub
		return baseServiceImpl.getById(MyResource.class, id);
	}

	@Override
	public MyResource getResourceByName(String name) throws Exception {
		// TODO Auto-generated method stub
		MyResource myResource = baseServiceImpl.findOne("from MyResource where name = ? ", new Object[] { name });
		return myResource;
	}

	@Override
	public List<MyResource> getResourcesByParentId(String id) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(MyResource.class);
		criteria.add(Restrictions.eq("parent.id", id));
		criteria.addOrder(Order.asc("ordernum"));
		return baseServiceImpl.findByCriteria(criteria);
	}

	@Override
	public MyResource updateResource(MyResource myResource) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.saveOrUpdate(myResource);
		return myResource;
	}

	@Override
	public MyResource getResourceId(String id) throws Exception {
		// TODO Auto-generated method stub
		return baseServiceImpl.getById(MyResource.class, id);
	}

	@Override
	public MyResource updateResourceState(String id, Boolean activite) throws Exception {
		// TODO Auto-generated method stub
		List<MyResource> temp = new ArrayList<MyResource>();
		MyResource myResource = baseServiceImpl.getById(MyResource.class, id);
		if (myResource != null) {
			List<MyResource> childrens = myResource.getChildrens();
			if (!activite) {
				for (MyResource children : childrens) {
					updateChildrenResourceState(children);
					children.setActivite(activite);
					temp.add(children);
				}
			}
			myResource.setActivite(activite);
			temp.add(myResource);
		}
		baseServiceImpl.save(temp);
		return myResource;
	}

	/**
	 * 禁用所有子资源
	 * 
	 * @param children
	 * @throws Exception
	 */
	public void updateChildrenResourceState(MyResource children) throws Exception {
		List<MyResource> childrens = children.getChildrens();
		List<MyResource> temp = new ArrayList<MyResource>();
		for (MyResource c : childrens) {
			updateChildrenResourceState(c);
			c.setActivite(false);
			temp.add(c);
		}
		baseServiceImpl.save(temp);
	}

	@Override
	public void deleteResourceById(String id) throws Exception {
		// TODO Auto-generated method stub
		baseServiceImpl.delete(MyResource.class, id);
	}

	@Override
	public List<MyResource> getAllParentResource() throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(MyResource.class);
		criteria.add(Restrictions.isNull("parent"));
		criteria.add(Restrictions.eq("activite", true));
		criteria.addOrder(Order.asc("ordernum"));
		List<MyResource> resources = baseServiceImpl.findByCriteria(criteria);
		return resources;
	}

	@SuppressWarnings("unchecked")
	public JSONArray geResourceChildren(MyResource myResource) throws Exception {
		JSONArray children = new JSONArray();
		List<MyResource> childrens = myResource.getChildrens();
		for (MyResource mr : childrens) {
			JSONObject r = new JSONObject();
			if (mr.getActivite()) {
				r.put("id", mr.getId());
				r.put("text", mr.getName());
				r.put("url", mr.getUrl());
				if (mr.getChildrens().size() > 0) {
					JSONArray cr = this.geResourceChildren(mr);
					r.put("children", cr);
				}
				children.add(r);
			}
		}
		return children;
	}

	@SuppressWarnings("unchecked")
	public JSONArray geResourceChildren(MyResource myResource, List<MyResource> roleResources, Boolean isSuperManager)
			throws Exception {
		JSONArray children = new JSONArray();
		DetachedCriteria criteria = DetachedCriteria.forClass(MyResource.class);
		criteria.add(Restrictions.eq("parent.id", myResource.getId()));
		criteria.addOrder(Order.asc("ordernum"));
		List<MyResource> childrens = myResource.getChildrens();
		Collections.sort(childrens);
		for (MyResource mr : childrens) {
			if (roleResources.contains(mr)) {
				JSONObject r = new JSONObject();
				if (isSuperManager) {
					r.put("id", mr.getId());
					r.put("text", mr.getName());
					r.put("url", mr.getUrl());
					if (mr.getChildrens().size() > 0) {
						JSONArray cr = this.geResourceChildren(mr);
						r.put("children", cr);
					}
					children.add(r);
				} else {
					if (mr.getActivite()) {
						r.put("id", mr.getId());
						r.put("text", mr.getName());
						r.put("url", mr.getUrl());
						if (mr.getChildrens().size() > 0) {
							JSONArray cr = this.geResourceChildren(mr);
							r.put("children", cr);
						}
						children.add(r);
					}
				}
			}
		}
		return children;
	}

	@Override
	public void addRoleResource(List<String> roleIds, List<String> resourceIds) throws Exception {
		// TODO Auto-generated method stub
		List<MyResource> resources = baseServiceImpl.getByIdList(MyResource.class, resourceIds);
		List<Role> roles = baseServiceImpl.getByIdList(Role.class, roleIds);
		// 删除旧的权限
		this.deleteOldRoleResources(roleIds);
		List<RoleResource> roleResources = new ArrayList<RoleResource>();
		for (Role role : roles) {
			for (MyResource myResource : resources) {
				RoleResource roleResource = new RoleResource(role, myResource);
				roleResources.add(roleResource);
			}
		}
		baseServiceImpl.save(roleResources);// 保存新的权限
	}

	@Override
	public List<RoleResource> getCurrentRoleResourceByRoleId(String id) throws Exception {
		// TODO Auto-generated method stub
		List<RoleResource> roleResources = baseServiceImpl.find("from RoleResource where role.id = ?",
				new Object[] { id });
		return roleResources;
	}

	@Override
	public void deleteOldRoleResources(List<String> roleIds) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(RoleResource.class);
		criteria.add(Restrictions.in("role.id", roleIds));
		List<RoleResource> oldRoleResources = baseServiceImpl.findByCriteria(criteria);
		baseServiceImpl.delete(oldRoleResources);// 删除旧的权限
	}

	@Override
	public List<MyResource> getUserMenusByUserId(String id, Boolean falg, Boolean isSuperManager) throws Exception {
		// TODO Auto-generated method stub
		// 根据用户ID获取用户所有角色
		DetachedCriteria criteria1 = DetachedCriteria.forClass(UserRole.class);
		criteria1.add(Restrictions.eq("user.id", id));
		List<UserRole> userRoles = baseServiceImpl.findByCriteria(criteria1);
		List<String> roleIds = new ArrayList<String>();
		for (UserRole userRole : userRoles) {
			roleIds.add(userRole.getRole().getId());
		}
		// 根据角色获取对应该角色的菜单资源
		DetachedCriteria criteria2 = DetachedCriteria.forClass(RoleResource.class);
		criteria2.createAlias("resource", "res");
		criteria2.createAlias("role", "ro");
		criteria2.add(Restrictions.eq("res.type", "菜单"));
		if (!isSuperManager) {
			criteria2.add(Restrictions.eq("res.activite", true));
		}
		criteria2.add(Restrictions.in("ro.id", roleIds));
		criteria2.addOrder(Order.asc("res.ordernum"));
		if (falg) {
			criteria2.add(Restrictions.isNull("res.parent"));
		}
		List<RoleResource> roleResources = baseServiceImpl.findByCriteria(criteria2);
		List<MyResource> resources = new ArrayList<MyResource>();
		for (RoleResource roleResource : roleResources) {
			resources.add(roleResource.getResource());
		}
		return resources;
	}

	@Override
	public Boolean isSuperMnager(String id) throws Exception {
		// TODO Auto-generated method stub
		DetachedCriteria criteria = DetachedCriteria.forClass(UserRole.class);
		criteria.add(Restrictions.eq("user.id", id));
		List<UserRole> userRoles = baseServiceImpl.findByCriteria(criteria);
		Boolean isSuperManager = false;
		for (UserRole userRole : userRoles) {
			if (userRole.getRole().getCode() == myConfig.getSuperManagerRoleCode()) {
				isSuperManager = true;
				break;
			}
		}
		return isSuperManager;
	}

	@Override
	public List<MyResource> getAllMyResource() throws Exception {
		// TODO Auto-generated method stub
		return baseServiceImpl.get(MyResource.class);
	}

	@Override
	public List<MyResource> getCurrentUserResourcesByUserId(String userId) throws Exception {
		// TODO Auto-generated method stub
		// 查询用户角色
		DetachedCriteria criteria = DetachedCriteria.forClass(UserRole.class);
		criteria.add(Restrictions.eq("user.id", userId));
		List<UserRole> userRoles = baseServiceImpl.findByCriteria(criteria);
		List<String> roleIds = new ArrayList<>();
		for (UserRole userRole : userRoles) {
			roleIds.add(userRole.getRole().getId());
		}
		// 根据角色查询角色对应的资源
		DetachedCriteria criteria2 = DetachedCriteria.forClass(RoleResource.class);
		//criteria2.createAlias("role", "ro");
		criteria2.add(Restrictions.in("role.id", roleIds));
		List<RoleResource> roleResources = baseServiceImpl.findByCriteria(criteria2);
		List<MyResource> resources = new ArrayList<MyResource>();
		for (RoleResource roleResource : roleResources) {
			resources.add(roleResource.getResource());
		}
		return resources;
	}
}
